package net.kleinhenz.droidshop.xml;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import net.kleinhenz.droidshop.DroidShop;
import net.kleinhenz.droidshop.model.Message;
import net.kleinhenz.droidshop.model.Motd;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.util.Log;

public class MotdXMLHandler extends DefaultHandler
{	
	// temporary objects
	private Motd motd = null;
	private Message message = null;
	private String currencyName = null;
	private double currencyValue = -1;
	
	// content
	private StringBuffer contentBuffer = new StringBuffer();
	
	// elements
	private boolean inMotd = false;
	private boolean inMessages = false;
	private boolean inMajor = false;
	private boolean inMinor = false;
	private boolean inMicro = false;
	private boolean inMessage = false;
	private boolean inLocale = false;
	private boolean inText = false;
	private boolean inCurrencies = false;
	private boolean inCurrency = false;
	private boolean inCurrencyName = false;
	private boolean inCurrencyValue = false;
	
	@Override
	public void startElement(String uri, String localName, String name,
			Attributes attributes) throws SAXException
	{
		String tName = localName.trim();
		// root element
		if (tName.equals("motd")) 
		{
			inMotd = true;
			motd = new Motd();
		}
		// elements
		if (inMotd && tName.equals("major"))
		{
			inMajor = true;
			emptyContentBuffer();
		}
		if (inMotd && tName.equals("minor"))
		{
			inMinor = true;
			emptyContentBuffer();
		}
		if (inMotd && tName.equals("micro"))
		{
			inMicro = true;
			emptyContentBuffer();
		}
		if (inMotd && tName.equals("messages"))
		{
			inMessages = true;
		}
		if (inMessages && tName.equals("message"))
		{
			inMessage = true;
			message = new Message();
		}
		if (inMessage && tName.equals("locale"))
		{
			inLocale = true;
			emptyContentBuffer();
		}
		if (inMessage && tName.equals("text"))
		{
			inText = true;
			emptyContentBuffer();
		}
		if (inMotd && tName.equals("currencies"))
		{
			inCurrencies = true;
		}
		if (inCurrencies && tName.equals("currency"))
		{
			inCurrency = true;
		}
		if (inCurrency && tName.equals("currencyname"))
		{
			inCurrencyName = true;
			emptyContentBuffer();
		}
		if (inCurrency && tName.equals("value"))
		{
			inCurrencyValue = true;
			emptyContentBuffer();
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String name)
			throws SAXException
	{
		String tName = localName.trim();
		// root element
		if (inMotd && tName.equals("motd"))
			inMotd = false;
		// top level elements
		if (inMajor && tName.equals("major"))
		{
			inMajor = false;
			motd.setVersionMajor(Integer.parseInt(contentBuffer.toString().trim()));
		}
		if (inMinor && tName.equals("minor"))
		{
			inMinor = false;
			motd.setVersionMinor(Integer.parseInt(contentBuffer.toString().trim()));
		}
		if (inMicro && tName.equals("micro"))
		{
			inMicro = false;
			motd.setVersionMicro(Integer.parseInt(contentBuffer.toString().trim()));
		}
		if (inMessages && tName.equals("messages"))
		{
			inMessages = false;
		}
		if (inMessage && tName.equals("message"))
		{
			inMessage = false;
			motd.getMessages().add(message);
			message = null;
		}
		if (inLocale && tName.equals("locale"))
		{
			inLocale = false;
			message.setLocale(contentBuffer.toString().trim());
		}
		if (inText && tName.equals("text"))
		{
			inText = false;
			message.setText(contentBuffer.toString().trim());
		}
		if (inMotd && tName.equals("currencies"))
		{
			inCurrencies = false;
		}
		if (inCurrencies && tName.equals("currency"))
		{
			inCurrency = false;
			if (currencyName!=null && currencyValue!=-1)
				DroidShop.currency.put(currencyName, currencyValue);
		}
		if (inCurrency && tName.equals("currencyname"))
		{
			inCurrencyName = false;
			currencyName = contentBuffer.toString().trim();
		}
		if (inCurrency && tName.equals("value"))
		{
			inCurrencyValue = false;
			currencyValue = Double.parseDouble(contentBuffer.toString().trim());
		}
	}
	
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException
	{
		if (inContent())
			contentBuffer.append(ch, start, length);
	}
	
	private boolean inContent()
	{
		return (inMajor || inMinor || inMicro || inLocale || inText || inCurrencyName || inCurrencyValue);
	}

	private void emptyContentBuffer()
	{
		contentBuffer.delete(0, contentBuffer.length());
	}
	
	/**
	 * Reads a DroidShopMotdXML document from the given URL. It returns the
	 * parsed Quest object containing all data read from the DroidShopXML.
	 * 
	 * @param url DroidShopMotdXML document URL.
	 * @return Quest object containing the story.
	 * @throws DroidShopXMLException if parsing fails.
	 */
	public Motd readDroidShopMotdXML(URL url) throws DroidShopXMLException 
	{
        try 
        {
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();
            XMLReader xr = sp.getXMLReader();
            xr.setContentHandler(this);
            xr.parse(new InputSource(url.openStream()));
        } 
        catch (IOException e) 
        {
            Log.e(DroidShop.APP_NAME, e.toString());
            throw new DroidShopXMLException("I/O error while reading DroidShopMotdXML.", e);
      	} 
        catch (SAXException e) 
      	{
            Log.e(DroidShop.APP_NAME, e.toString());
            throw new DroidShopXMLException("SAX error while reading DroidShopMotdXML.", e);
        } 
        catch (ParserConfigurationException e) 
        {
            Log.e(DroidShop.APP_NAME, e.toString());
            throw new DroidShopXMLException("Parse error while reading DroidShopMotdXML.", e);
        } 
        catch (IllegalArgumentException e) 
        {
        	Log.e(DroidShop.APP_NAME, e.toString());
        	throw new DroidShopXMLException("Parse error while getting type information.", e);
        }
        
        return motd;
    }

	public Motd readDroidShopMotdXML(InputStream is) throws DroidShopXMLException 
	{
        try 
        {
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();
            XMLReader xr = sp.getXMLReader();
            xr.setContentHandler(this);
            xr.parse(new InputSource(is));
        } 
        catch (IOException e) 
        {
            Log.e(DroidShop.APP_NAME, e.toString());
            throw new DroidShopXMLException("I/O error while reading DroidShopMotdXML.", e);
      	} 
        catch (SAXException e) 
        {
            Log.e(DroidShop.APP_NAME, e.toString());
            throw new DroidShopXMLException("SAX error while reading DroidShopMotdXML.", e);
        } 
        catch (ParserConfigurationException e) 
        {
            Log.e(DroidShop.APP_NAME, e.toString());
            throw new DroidShopXMLException("Parse error while reading DroidShopMotdXML.", e);
        } 
        catch (IllegalArgumentException e) 
        {
        	Log.e(DroidShop.APP_NAME, e.toString());
        	throw new DroidShopXMLException("Parse error while getting type information.", e);
        }
        
        return motd;
    }
}

